/*******************************************************************************
 * Copyright (c) 2000, 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Author:
 *     coolair.loveU2@gmail.com
 *******************************************************************************/

package org.skyfree.ghyll.tcard.core.internal;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.skyfree.ghyll.tcard.core.IStoragePath;
import org.skyfree.ghyll.tcard.core.ITCard;
import org.skyfree.ghyll.tcard.core.ITProject;
import org.skyfree.ghyll.tcard.core.ITRepository;
import org.skyfree.ghyll.tcard.core.ITWorkpiece;
import org.skyfree.ghyll.tcard.core.TCardCore;

/**
 * This class ...
 */

public class TWorkpiece extends AbstractTResource implements ITWorkpiece,Comparable<TWorkpiece>
{
	TProject project = null;
	TRepository repository = null;
	ITWorkpiece progress = null;
	protected String name;
	protected String uniqueID;
	protected String description;
	protected TCard rootCard; 
	protected boolean inProgress;
	protected String  storageType;
	protected boolean isProgressType = false;
	
	HashMap<String,String[]> treeMapping;
	private IStoragePath linkPath;
	
	public TWorkpiece(IStoragePath path,String name)
	{
		super(path);
		this.name = name;
	}

	@Override
	public void create(String uniqueID, String name, String description)
			throws CoreException
	{
		
		this.uniqueID = uniqueID;
		this.name = name;
		if(description==null)this.description="";
		else this.description = description;
		this.loaded = true;
		this.storageType = ITWorkpiece.STT_Original;
		this.save();
		this.project.cacheWorkPiece.put(name, this);
	}
	

	@Override
	public String getDescription()
	{
		return this.description;
	}

	@Override
	public String getName()
	{
		return this.name;
	}

	@Override
	public ITCard getRoot()
	{
		if(this.rootCard==null)
		{
			if(this.loaded)return null;
			try
			{
				if(this.treeMapping.get("/")!=null)
				{
					String root = this.treeMapping.get("/")[0];
					this.rootCard = new TCard(getCardPath(root),null,root,this);
					RecursiveLoad(rootCard);
				}
				this.loaded = true;
			} catch (Exception e)
			{
				this.log(e);
				this.rootCard = null;
				return null;
			}
		}
		return this.rootCard;
	}
	
	public IStoragePath getCardPath(String name)
	{
		if(this.storageType==ITWorkpiece.STT_Link)
			return this.linkPath.append(name);
		else return this.path.append(name);
	}
	
	private void RecursiveLoad(TCard parent) throws Exception
	{
		this.provider.load(parent);
		String[] subNames = this.treeMapping.get(parent.name);
		for(int i=0;i<subNames.length;i++)
		{
			TCard sub = new TCard(getCardPath(subNames[i]),parent,subNames[i],this);
			parent.setComposite(true);
			RecursiveLoad(sub);
		}		
	}
	
	@Override
	public String getUniqueID()
	{
		return this.uniqueID;
	}

	@Override
	public void save2Repository()
	{
		// TODO Auto-generated method stub

	}

	@SuppressWarnings("unchecked")
	@Override
	public Object getAdapter(Class adapter)
	{
		if (adapter == ITProject.class) {
			return this.project;			
		}
		else if(adapter == ITRepository.class) {
			return this.repository;			
		}
		return null;
	}

	@Override
	public void load() throws CoreException
	{
		try
		{
			if(this.isProgressType)
			{
				this.provider.loadInProgressWorkpiece(this);
				this.loaded = true;
			}
			this.treeMapping = this.provider.load(this);
			
		} catch (Exception e)
		{
			this.log(e);
			throw new CoreException(new Status(IStatus.ERROR,TCardCore.PLUGIN_ID,e.getMessage()));
		}
	}

	@Override
	public void reload() throws CoreException
	{
		this.rootCard = null;
		this.loaded = false;
		this.load();

	}

	@Override
	public void save() throws CoreException
	{
		try
		{
			this.provider.save(this);
		} catch (Exception e)
		{
			this.log(e);
			throw new CoreException(new Status(IStatus.ERROR,TCardCore.PLUGIN_ID,e.getMessage()));
		}
	}

	@Override
	public void setDescription(String description)
	{
		this.description = description;
		
	}

	@Override
	public void setName(String name)
	{
		this.name = name;
		
	}

	@Override
	public void setUniqueID(String uniqueID)
	{
		this.uniqueID = uniqueID;
		
	}

	@Override
	public ITCard createTCard(ITCard parent, String name,boolean isComp,boolean needSave) throws CoreException
	{
		TCard newCard = new TCard(this.getCardPath(name),parent,name,this);
		newCard.setComposite(isComp);
		
		if(parent!=null)
		{
			parent.setComposite(true);
			String[] now = this.treeMapping.get(parent.getItemName());
			String[] update = new String[now.length+1];
			System.arraycopy(now, 0, update, 0, now.length);
			update[now.length] = name;
			this.treeMapping.put(parent.getItemName(),update);
			this.treeMapping.put(name, new String[0]);
		}
		else
		{
			this.rootCard = newCard;
			if(this.treeMapping==null)this.treeMapping = new HashMap<String,String[]>();
			this.treeMapping.put("/",new String[]{this.rootCard.getItemName()});
			//this.treeMapping.put(name,new String[]{this.rootCard.getItemName()});
			this.treeMapping.put(name,new String[0]);
		}
		if(needSave)
		{
			newCard.save();
			this.save();
		}
		return newCard;
	}

	

	@Override
	public boolean existCard(String name) 
	{
		return this.treeMapping.containsKey(name);
	}

	@Override
	public void delete() 
	{
		try {
			this.provider.delete(this);
			if(this.project!=null)this.project.cacheWorkPiece.remove(this.name);
			else
			{
				/**
				 * Workpiece in repository
				 */
				return;
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

	void deleteMap(ITCard sub) 
	{
		this.treeMapping.remove(sub.getItemName());
		if(sub.getParent()==null)
		{
			this.treeMapping.remove("/");
		}
		Iterator<ITCard> it = sub.getSubTCard().iterator();
		while(it.hasNext())
		{
			deleteMap(it.next());
		}
		
	}

	@Override
	public boolean isInProgress() 
	{
		return this.inProgress;
	}

	@Override
	public void move2Progress() 
	{
		try {
			this.provider.move2Progress(this);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			this.log(new CoreException(new Status(IStatus.ERROR,TCardCore.PLUGIN_ID,e.getMessage())));
		}
		this.inProgress = true;
	}
	
	@Override
	public void move2Home() {
		try {
			this.provider.move2Home(this);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			this.log(new CoreException(new Status(IStatus.ERROR,TCardCore.PLUGIN_ID,e.getMessage())));
		}
		this.inProgress = false;
		
	}

	
	@Override
	public void setInProgress(boolean isInpro) 
	{
		this.inProgress = isInpro;
	}

	@Override
	public ITWorkpiece adapter4Inprogress() 
	{
		if(!this.inProgress)return null;
		try {
			if(this.progress==null)
			{
				this.progress = (ITWorkpiece) TCardCore.create(ITWorkpiece.class,this.getPath());
				this.progress.setName(this.getName());
				this.progress.setProgressType();
				this.progress.load();
			}
			return this.progress;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			this.log(new CoreException(new Status(IStatus.ERROR,TCardCore.PLUGIN_ID,e.getMessage())));
		}
		return null;
	}

	@Override
	public String getStorageType() 
	{
		return this.storageType;
	}

	@Override
	public void setStorageType(String stype) 
	{
		this.storageType = stype;
		
	}

	@Override
	public boolean isProgressType() {
		return this.isProgressType;
	}

	@Override
	public void setProgressType() {
		this.isProgressType = true;
	}

	@Override
	public String[] getAllCardNames() {
		ArrayList<String> result = new ArrayList<String>();
		result.addAll(this.treeMapping.keySet());
		result.remove("/");
		String[] re = new String[result.size()];
		return result.toArray(re);
	}

	@Override
	public void setLinkPath(IStoragePath linkPath) {
		this.linkPath = linkPath;
		
	}

	@Override
	public IStoragePath getLinkPath() {
		return this.linkPath;
	}

	@Override
	public void setProject(ITProject project) {
		this.project = (TProject) project;
	}

	@Override
	public int compareTo(TWorkpiece o) {
		return this.name.compareTo(o.getName());
	}	
}
